/* $Id: log.h 3752 2011-09-18 14:38:46Z bennylp $ */
/* 
 * Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com)
 * Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA 
 */
#ifndef __CSVT_LOG_H__
#define __CSVT_LOG_H__

/**
 * @file log.h
 * @brief Logging Utility.
 */

#include <assert.h>
#include <stdarg.h>
#include <string.h>
#include <stdio.h>
//#include <linux/time.h>
#include <sys/time.h> 
#include <pthread.h>


/**
 * @defgroup CSVT_MISC Miscelaneous
 */

/**
 * @defgroup CSVT_LOG Logging Facility
 * @ingroup CSVT_MISC
 * @{
 *
 * The CSVTLIB logging facility is a configurable, flexible, and convenient
 * way to write logging or trace information.
 *
 * To write to the log, one uses construct like below:
 *
 * <pre>
 *   ...
 *   CSVT_LOG(3, ("main.c", "Starting hello..."));
 *   ...
 *   CSVT_LOG(3, ("main.c", "Hello world from process %d", CSVT_getpid()));
 *   ...
 * </pre>
 *
 * In the above example, the number @b 3 controls the verbosity level of
 * the information (which means "information", by convention). The string
 * "main.c" specifies the source or sender of the message.
 *
 *
 * \section CSVT_log_quick_sample_sec Examples
 *
 * For examples, see:
 *  - @ref page_CSVTlib_samples_log_c.
 *
 */


/** Color type. */
typedef unsigned int CSVT_color_t;
typedef unsigned int CSVT_status_t;
/** Thread handle. */
typedef pthread_t CSVT_thread_t;

typedef struct csvt_domain_log csvt_domain_log;

#define CSVT_SUCCESS 0 
#define CSVT_TRUE 0
#define CSVT_FALSE -1
#define CSVT_LOG_MAX_LEVEL  6
typedef char  CSVT_bool_t ;

/*
 * Terminal.
 */
/**
 * Color code combination.
 */
enum {
    CSVT_TERM_COLOR_R	= 2,    /**< Red            */
    CSVT_TERM_COLOR_G	= 4,    /**< Green          */
    CSVT_TERM_COLOR_B	= 1,    /**< Blue.          */
    CSVT_TERM_COLOR_BRIGHT = 8    /**< Bright mask.   */
};

#   define CSVT_LOG_INDENT_SIZE        1



/**
 * @}
 */
/**
 * @addtogroup CSVT_TIME Time Data Type and Manipulation.
 * @ingroup CSVT_MISC
 * @{
 */

/**
 * Representation of time value in this library.
 * This type can be used to represent either an interval or a specific time
 * or date. 
 */
typedef struct CSVT_time_val
{
    /** The seconds part of the time. */
    long    sec;

    /** The miliseconds fraction of the time. */
    long    msec;

} CSVT_time_val;



/**
 * This structure represent the parsed representation of time.
 * It is acquired by calling #CSVT_time_decode().
 */
typedef struct CSVT_parsed_time
{
    /** This represents day of week where value zero means Sunday */
    int wday;

    /* This represents day of the year, 0-365, where zero means
     *  1st of January.
     */
    int yday; 

    /** This represents day of month: 1-31 */
    int day;

    /** This represents month, with the value is 0 - 11 (zero is January) */
    int mon;

    /** This represent the actual year (unlike in ANSI libc where
     *  the value must be added by 1900).
     */
    int year;

    /** This represents the second part, with the value is 0-59 */
    int sec;

    /** This represents the minute part, with the value is: 0-59 */
    int min;

    /** This represents the hour part, with the value is 0-23 */
    int hour;

    /** This represents the milisecond part, with the value is 0-999 */
    int msec;

} CSVT_parsed_time;



/*
 * OS.
 */
 
 #if 0
typedef struct CSVT_mutex_t
{
    pthread_mutex_t     mutex;
    char		obj_name[32];

}CSVT_mutex_t;
//typedef pthread_t CSVT_thread_t;
#endif
//const char* CSVT_thread_get_name(CSVT_thread_t *p);
//CSVT_thread_t* CSVT_thread_this(void);

/*
 * String
 */


int CSVT_utoa(unsigned long val, char *buf);
int CSVT_utoa_pad( unsigned long val, char *buf, int min_dig, int pad);


/**
 * Log decoration flag, to be specified with #CSVT_log_set_decor().
 */
enum CSVT_log_decoration
{
    CSVT_LOG_HAS_DAY_NAME   =    1, /**< Include day name [default: no] 	      */
    CSVT_LOG_HAS_YEAR       =    2, /**< Include year digit [no]		      */
    CSVT_LOG_HAS_MONTH	  =    4, /**< Include month [no]		      */
    CSVT_LOG_HAS_DAY_OF_MON =    8, /**< Include day of month [no]	      */
    CSVT_LOG_HAS_TIME	  =   16, /**< Include time [yes]		      */
    CSVT_LOG_HAS_MICRO_SEC  =   32, /**< Include microseconds [yes]             */
    CSVT_LOG_HAS_SENDER	  =   64, /**< Include sender in the log [yes] 	      */
    CSVT_LOG_HAS_NEWLINE	  =  128, /**< Terminate each call with newline [yes] */
    CSVT_LOG_HAS_CR	  =  256, /**< Include carriage return [no] 	      */
    CSVT_LOG_HAS_SPACE	  =  512, /**< Include two spaces before log [yes]    */
    CSVT_LOG_HAS_COLOR	  = 1024, /**< Colorize logs [yes on win32]	      */
    CSVT_LOG_HAS_LEVEL_TEXT = 2048, /**< Include level text string [no]	      */
    CSVT_LOG_HAS_FUNCIONT_NAME  = 4096, /**< Include funciont name [no]     */
    CSVT_LOG_HAS_THREAD_SWC = 8192, /**< Add mark when thread has switched [yes]*/
    CSVT_LOG_HAS_INDENT     =16384,  /**< Indentation. Say yes! [yes]            */
    CSVT_LOG_HAS_LINE     =32768  /**< Line MSG. [yes]            */
};

/**
 * Write log message.
 * This is the main macro used to write text to the logging backend. 
 *
 * @param level	    The logging verbosity level. Lower number indicates higher
 *		    importance, with level zero indicates fatal error. Only
 *		    numeral argument is permitted (e.g. not variable).
 * @param arg	    Enclosed 'printf' like arguments, with the first 
 *		    argument is the sender, the second argument is format 
 *		    string and the following arguments are variable number of 
 *		    arguments suitable for the format string.
 *
 * Sample:
 * \verbatim
   CSVT_LOG(2, (__FILE__, "current value is %d", value));
   \endverbatim
 * @hideinitializer
 */
#define CSVT_LOG(level,arg)	do { \
				    if (level <= CSVT_log_get_level()) \
					CSVT_log_wrapper_##level(arg); \
				} while (0)

/**
 * Signature for function to be registered to the logging subsystem to
 * write the actual log message to some output device.
 *
 * @param level	    Log level.
 * @param data	    Log message, which will be NULL terminated.
 * @param len	    Message length.
 */
typedef void CSVT_log_func(struct csvt_domain_log *obj,int level, const char *data, int len);

/**
 * Default logging writer function used by front end logger function.
 * This function will print the log message to stdout only.
 * Application normally should NOT need to call this function, but
 * rather use the CSVT_LOG macro.
 *
 * @param level	    Log level.
 * @param buffer    Log message.
 * @param len	    Message length.
 */
void CSVT_log_write(struct csvt_domain_log *obj,int level, const char *buffer, int len);

void CSVT_log_write_to_file(struct csvt_domain_log *obj,int level, const char *buffer, int len);
//#if CSVT_LOG_MAX_LEVEL >= 1

/**
 * Write to log.
 *
 * @param sender    Source of the message.
 * @param level	    Verbosity level.
 * @param format    Format.
 * @param marker    Marker.
 */
void CSVT_log(struct csvt_domain_log *obj,const char *sender, int level, 
		     const char *format, va_list marker);

/**
 * Change log output function. The front-end logging functions will call
 * this function to write the actual message to the desired device. 
 * By default, the front-end functions use CSVT_log_write() to write
 * the messages, unless it's changed by calling this function.
 *
 * @param func	    The function that will be called to write the log
 *		    messages to the desired device.
 */
void CSVT_log_set_log_func( struct csvt_domain_log *obj,int level,CSVT_log_func *func );

/**
 * Get the current log output function that is used to write log messages.
 *
 * @return	    Current log output function.
 */
CSVT_log_func* CSVT_log_get_log_func(struct csvt_domain_log *obj,int level);

/**
 * Set maximum log level. Application can call this function to set 
 * the desired level of verbosity of the logging messages. The bigger the
 * value, the more verbose the logging messages will be printed. However,
 * the maximum level of verbosity can not exceed compile time value of
 * CSVT_LOG_MAX_LEVEL.
 *
 * @param level	    The maximum level of verbosity of the logging
 *		    messages (6=very detailed..1=error only, 0=disabled)
 */
void CSVT_log_set_level(struct csvt_domain_log *obj,int level);

/**
 * Get current maximum log verbositylevel.
 *
 * @return	    Current log maximum level.
 */

int CSVT_log_get_level(struct csvt_domain_log *obj);


/**
 * Set log decoration. The log decoration flag controls what are printed
 * to output device alongside the actual message. For example, application
 * can specify that date/time information should be displayed with each
 * log message.
 *
 * @param decor	    Bitmask combination of #CSVT_log_decoration to control
 *		    the layout of the log message.
 */
void CSVT_log_set_decor(struct csvt_domain_log *obj,unsigned decor);

/**
 * Get current log decoration flag.
 *
 * @return	    Log decoration flag.
 */
unsigned CSVT_log_get_decor(struct csvt_domain_log *obj);

/**
 * Add indentation to log message. Indentation will add CSVT_LOG_INDENT_CHAR
 * before the message, and is useful to show the depth of function calls.
 *
 * @param indent    The indentation to add or substract. Positive value
 * 		    adds current indent, negative value subtracts current
 * 		    indent.
 */
void CSVT_log_add_indent(struct csvt_domain_log *obj,int indent);

/**
 * Push indentation to the right by default value (CSVT_LOG_INDENT).
 */
void CSVT_log_push_indent(struct csvt_domain_log *obj);

/**
 * Pop indentation (to the left) by default value (CSVT_LOG_INDENT).
 */
void CSVT_log_pop_indent(struct csvt_domain_log *obj);

/**
 * Set color of log messages.
 *
 * @param level	    Log level which color will be changed.
 * @param color	    Desired color.
 */
void CSVT_log_set_color(struct csvt_domain_log *obj,int level, CSVT_color_t color);

/**
 * Get color of log messages.
 *
 * @param level	    Log level which color will be returned.
 * @return	    Log color.
 */
CSVT_color_t CSVT_log_get_color(struct csvt_domain_log *obj,int level);

/**
 * Internal function to be called by CSVT_init()
 */
CSVT_status_t CSVT_log_init(struct csvt_domain_log*);

//#else	/* #if CSVT_LOG_MAX_LEVEL >= 1 */
#if 0
/**
 * Change log output function. The front-end logging functions will call
 * this function to write the actual message to the desired device. 
 * By default, the front-end functions use CSVT_log_write() to write
 * the messages, unless it's changed by calling this function.
 *
 * @param func	    The function that will be called to write the log
 *		    messages to the desired device.
 */
#  define CSVT_log_set_log_func(struct csvt_domain_log *obj,func)

/**
 * Set maximum log level. Application can call this function to set 
 * the desired level of verbosity of the logging messages. The bigger the
 * value, the more verbose the logging messages will be printed. However,
 * the maximum level of verbosity can not exceed compile time value of
 * CSVT_LOG_MAX_LEVEL.
 *
 * @param level	    The maximum level of verbosity of the logging
 *		    messages (6=very detailed..1=error only, 0=disabled)
 */
#  define CSVT_log_set_level(struct csvt_domain_log *obj,level)

/**
 * Set log decoration. The log decoration flag controls what are printed
 * to output device alongside the actual message. For example, application
 * can specify that date/time information should be displayed with each
 * log message.
 *
 * @param decor	    Bitmask combination of #CSVT_log_decoration to control
 *		    the layout of the log message.
 */
#  define CSVT_log_set_decor(struct csvt_domain_log *obj,decor)

/**
 * Set color of log messages.
 *
 * @param level	    Log level which color will be changed.
 * @param color	    Desired color.
 */
#  define CSVT_log_set_color(struct csvt_domain_log *obj,level, color)

/**
 * Get current maximum log verbositylevel.
 *
 * @return	    Current log maximum level.
 */
#  define CSVT_log_get_level(struct csvt_domain_log *obj)	0

/**
 * Get current log decoration flag.
 *
 * @return	    Log decoration flag.
 */
#  define CSVT_log_get_decor(struct csvt_domain_log *obj)	0

/**
 * Get color of log messages.
 *
 * @param level	    Log level which color will be returned.
 * @return	    Log color.
 */
#  define CSVT_log_get_color(struct csvt_domain_log *obj,level) 0


/**
 * Internal.
 */
//#   define CSVT_log_init()	CSVT_SUCCESS
#endif

//#endif	/* #if CSVT_LOG_MAX_LEVEL >= 1 */

/** 
 * @}
 */

/* **************************************************************************/
/*
 * Log functions implementation prototypes.
 * These functions are called by CSVT_LOG macros according to verbosity
 * level specified when calling the macro. Applications should not normally
 * need to call these functions directly.
 */

/**
 * @def CSVT_log_wrapper_1(arg)
 * Internal function to write log with verbosity 1. Will evaluate to
 * empty expression if CSVT_LOG_MAX_LEVEL is below 1.
 * @param arg       Log expression.
 */
#if CSVT_LOG_MAX_LEVEL >= 1
    #define CSVT_log_wrapper_1(arg)	CSVT_log_1 arg
    /** Internal function. */
    //void CSVT_log_1(struct csvt_domain_log *obj,const char *src, const char *format, ...);
	void CSVT_log_1(struct csvt_domain_log *obj,const char *src, const char *format, va_list arg);
#else
    #define CSVT_log_wrapper_1(arg)
#endif

/**
 * @def CSVT_log_wrapper_2(arg)
 * Internal function to write log with verbosity 2. Will evaluate to
 * empty expression if CSVT_LOG_MAX_LEVEL is below 2.
 * @param arg       Log expression.
 */
#if CSVT_LOG_MAX_LEVEL >= 2
    #define CSVT_log_wrapper_2(arg)	CSVT_log_2 arg
    /** Internal function. */
    //void CSVT_log_2(struct csvt_domain_log *obj,const char *src, const char *format, ...);
	void CSVT_log_2(struct csvt_domain_log *obj,const char *src, const char *format, va_list arg);
#else
    #define CSVT_log_wrapper_2(arg)
#endif

/**
 * @def CSVT_log_wrapper_3(arg)
 * Internal function to write log with verbosity 3. Will evaluate to
 * empty expression if CSVT_LOG_MAX_LEVEL is below 3.
 * @param arg       Log expression.
 */
#if CSVT_LOG_MAX_LEVEL >= 3
    #define CSVT_log_wrapper_3(arg)	CSVT_log_3 arg
    /** Internal function. */
    //void CSVT_log_3(struct csvt_domain_log *obj,const char *src, const char *format, ...);
	void CSVT_log_3(struct csvt_domain_log *obj,const char *src, const char *format, va_list arg);
#else
    #define CSVT_log_wrapper_3(arg)
#endif

/**
 * @def CSVT_log_wrapper_4(arg)
 * Internal function to write log with verbosity 4. Will evaluate to
 * empty expression if CSVT_LOG_MAX_LEVEL is below 4.
 * @param arg       Log expression.
 */
#if CSVT_LOG_MAX_LEVEL >= 4
    #define CSVT_log_wrapper_4(arg)	CSVT_log_4 arg
    /** Internal function. */
    //void CSVT_log_4(struct csvt_domain_log *obj,const char *src, const char *format, ...);
	void CSVT_log_4(struct csvt_domain_log *obj,const char *src, const char *format, va_list arg);
#else
    #define CSVT_log_wrapper_4(arg)
#endif

/**
 * @def CSVT_log_wrapper_5(arg)
 * Internal function to write log with verbosity 5. Will evaluate to
 * empty expression if CSVT_LOG_MAX_LEVEL is below 5.
 * @param arg       Log expression.
 */
#if CSVT_LOG_MAX_LEVEL >= 5
    #define CSVT_log_wrapper_5(arg)	CSVT_log_5 arg
    /** Internal function. */
    //void CSVT_log_5(struct csvt_domain_log *obj,const char *src, const char *format, ...);
	void CSVT_log_5(struct csvt_domain_log *obj,const char *src, const char *format, va_list arg);
#else
    #define CSVT_log_wrapper_5(arg)
#endif

/**
 * @def CSVT_log_wrapper_6(arg)
 * Internal function to write log with verbosity 6. Will evaluate to
 * empty expression if CSVT_LOG_MAX_LEVEL is below 6.
 * @param arg       Log expression.
 */
#if CSVT_LOG_MAX_LEVEL >= 6
    #define CSVT_log_wrapper_6(arg)	CSVT_log_6 arg
    /** Internal function. */
    //void CSVT_log_6(struct csvt_domain_log *obj,const char *src, const char *format, ...);
	void CSVT_log_6(struct csvt_domain_log *obj,const char *src, const char *format, va_list arg);
#else
    #define CSVT_log_wrapper_6(arg)
#endif

void CSVT_log_null(struct csvt_domain_log *obj,const char *src, const char *format, va_list arg);

//=============================add domain control============================================



 
//typedef void (*LOG_IMP)(struct csvt_domain_log *obj,const char *sender, const char *format, ...);
typedef void (*FN_LOG_IMP)(struct csvt_domain_log *obj,const char *sender, const char *format, va_list marker);

struct csvt_domain_log
{
    
    const char              *description;
    const char              *name;
    int                      name_len;
    unsigned int             age;
    char                     registered;
    
    int                      log_max_level;
    int                      log_indent;
    CSVT_log_func            *log_writer[7];//max 7 level 
	FILE					 *fp[7];//log_writer use it
    unsigned                 log_decor;
    CSVT_color_t             log_level_color[8];
    
    int                      line_ptr;
    const char               *fun_name;
    
    struct{
        FN_LOG_IMP E;
        FN_LOG_IMP W;
        FN_LOG_IMP I;
        FN_LOG_IMP D;
        FN_LOG_IMP T;
        FN_LOG_IMP V;
    };
    
};


/**********************************************************************************************************************/

 void csvt_domain_log_init( const char *name,csvt_domain_log *csvt );


/**
 * @def D_LOG_DOMAIN( _name, _description)
 * Internal function Define CSVT .
 * If you don't know what you do ,leave it!
 * @param _name       _description.
 */
 
#define D_LOG_DOMAIN(  _name, _description )                                                           \
     static  csvt_domain_log CSVT  = {                                                               \
            _description, #_name, sizeof(#_name) - 1, 0, 0, 0,0                                   \
     }; \
     D_LOG_SETUP(_name,CSVT) 
	
     


#define D_LOG_SETUP(shortname,obj)                                             \
__attribute__((constructor)) void csvt_##shortname##_ctor( void );          \
__attribute__((destructor))  void csvt_##shortname##_dtor( void );          \
                                                                                \
void                                                                            \
csvt_##shortname##_ctor( void )                                             \
{                                                                               \
     printf("Init \'%s\' ,Des:%s\n",#shortname,(obj).description);                  \
     csvt_domain_log_init( #shortname,&obj ); \
}                                                                               \
                                                                                \
void                                                                            \
csvt_##shortname##_dtor( void )                                             \
{                                                                               \
      printf("DeInit %s!\n",#shortname);                   \
	  csvt_domain_log_exit(&obj);	\
}   \
void static _csvt_e(const char *file_name,const char *fn,int line,char *x,...){ 	\
						CSVT.fun_name=fn;CSVT.line_ptr=line;					\
						va_list arg;va_start(arg, x);	\
						CSVT.E(&CSVT,file_name,x,arg);								\
						va_end(arg);	\
						}	\
void static _csvt_w(const char *file_name,const char *fn,int line,char *x,...){ 	\
						CSVT.fun_name=fn;CSVT.line_ptr=line;					\
						va_list arg;va_start(arg, x);	\
						CSVT.W(&CSVT,file_name,x,arg);								\
						va_end(arg);	\
						}	\
void static _csvt_i(const char *file_name,const char *fn,int line,char *x,...){ 	\
						CSVT.fun_name=fn;CSVT.line_ptr=line;					\
						va_list arg;va_start(arg, x);	\
						CSVT.I(&CSVT,file_name,x,arg);								\
						va_end(arg);	\
						}	\
void static _csvt_d(const char *file_name,const char *fn,int line,char *x,...){ 	\
						CSVT.fun_name=fn;CSVT.line_ptr=line;					\
						va_list arg;va_start(arg, x);	\
						CSVT.D(&CSVT,file_name,x,arg);								\
						va_end(arg);	\
						}	\
void static _csvt_t(const char *file_name,const char *fn,int line,char *x,...){ 	\
						CSVT.fun_name=fn;CSVT.line_ptr=line;					\
						va_list arg;va_start(arg, x);	\
						CSVT.T(&CSVT,file_name,x,arg);								\
						va_end(arg);	\
						}	\
void static _csvt_v(const char *file_name,const char *fn,int line,char *x,...){ 	\
						CSVT.fun_name=fn;CSVT.line_ptr=line;					\
						va_list arg;va_start(arg, x);	\
						CSVT.V(&CSVT,file_name,x,arg);								\
						va_end(arg);	\
						}	

#define csvt_e(x...) _csvt_e(__FILE__,__FUNCTION__,__LINE__,x)
#define csvt_w(x...) _csvt_w(__FILE__,__FUNCTION__,__LINE__,x)
#define csvt_i(x...) _csvt_i(__FILE__,__FUNCTION__,__LINE__,x)
#define csvt_d(x...) _csvt_d(__FILE__,__FUNCTION__,__LINE__,x)
#define csvt_t(x...) _csvt_t(__FILE__,__FUNCTION__,__LINE__,x)
#define csvt_v(x...) _csvt_v(__FILE__,__FUNCTION__,__LINE__,x)

#define dpl_e(x...) _csvt_e(__FILE__,__FUNCTION__,__LINE__,x)
#define dpl_w(x...) _csvt_w(__FILE__,__FUNCTION__,__LINE__,x)
#define dpl_i(x...) _csvt_i(__FILE__,__FUNCTION__,__LINE__,x)
#define dpl_d(x...) _csvt_d(__FILE__,__FUNCTION__,__LINE__,x)
#define dpl_t(x...) _csvt_t(__FILE__,__FUNCTION__,__LINE__,x)
#define dpl_v(x...) _csvt_v(__FILE__,__FUNCTION__,__LINE__,x)


/**********************************************************************************************************************/



#endif  /* __CSVT_LOG_H__ */

